package util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;

import jmetal.core.Solution;
import jmetal.core.SolutionSet;
import jmetal.util.Distance;

public class Calc {

	// return all points intermediates
	public static ArrayList<double[]> pointsEmptyOld(SolutionSet set) {
		ArrayList<double[]> resp = new ArrayList<double[]>();
		Distance d = new Distance();
		HashSet<Double> distances = new HashSet<Double>();

		Solution s1 = null, s2 = null;
		Solution s1Best = null, s2Best = null;

		if (set.size() > 1) {
			// number of gaps
			for (int n = 0; n < set.size() - 1; n++) {

				double maxDistance = -1;

				for (int i = 0; i < set.size(); i++) {
					for (int j = 0; j < set.size(); j++) {
						if (Math.abs(i - j) <= 1 && j != i) {
							s1 = set.get(i);
							s2 = set.get(j);

							double distance = d.distanceBetweenObjectives(s1,
									s2);
							if (distance > maxDistance
									&& !distances.contains(distance)) {
								maxDistance = distance;
								s1Best = s1;
								s2Best = s2;
							}
						}
					}
				}

				if (maxDistance > 0) {

					double[] r = new double[s1Best.getNumberOfObjectives()];

					for (int i = 0; i < s1Best.getNumberOfObjectives(); i++) {
						r[i] = (s1Best.getObjective(i) + s2Best.getObjective(i)) / 2;
					}

					distances.add(maxDistance);
					resp.add(r);
				}
			}
		}

		return resp;
	}

	public static ArrayList<double[]> pointsEmpty(SolutionSet set2) {
		ArrayList<double[]> resp = new ArrayList<double[]>();
		//Distance d = new Distance();

		Solution s1 = null, s2 = null;
		
		ArrayList<Solution> set = new ArrayList<Solution>();		
		for(int i = 0 ; i< set2.size(); i++)
		{
			set.add(set2.get(i));
		}
		
		//sort of objectives
		Collections.sort(set, new MySolutionComparator());
		
		for(int i = 0; i< set.size()-1; i++)
		{
			s1 = set.get(i);
			s2 = set.get(i+1);

			double[] r = new double[s1.getNumberOfObjectives()];

			for (int index = 0; index < s1.getNumberOfObjectives(); index++) {
				r[index] = (s1.getObjective(index) + s2
						.getObjective(index)) / 2;
			}
			resp.add(r);
		}

/*
		double[][] matrix = d.distanceMatrix(set);
		boolean[][] marked = new boolean[matrix.length][matrix[0].length];

		ArrayList<Double> l;

		for (int i = 0; i < matrix.length; i++) {
			
			l = new ArrayList<Double>();
			for (int j = 0; j < matrix[i].length; j++) {
				l.add(matrix[i][j]);
			}

			Collections.sort(l);

			// pega a terceira distancia - vizinho mais distante
			double value = Double.MAX_VALUE;
			int k = 1;
			while (l.get(k) == 0) {
				k++;
			}
			value = l.get(k);

			boolean find = false;

			while (!find) {
				for (int j = 0; j < matrix[i].length; j++) {
					if (matrix[i][j] == value) {
						if (marked[i][j]){
							value = l.get(++k);
							break;
						}
						else{
							find = true;
							break;
						}
					}
				}
			}

			for (int j = 0; j < matrix[i].length; j++) {
				if (matrix[i][j] == value && !marked[i][j]) {
					s1 = set.get(i);
					s2 = set.get(j);

					double[] r = new double[s1.getNumberOfObjectives()];

					for (int index = 0; index < s1.getNumberOfObjectives(); index++) {
						r[index] = (s1.getObjective(index) + s2
								.getObjective(index)) / 2;
					}
					resp.add(r);
					marked[i][j] = true;
					marked[j][i] = true;
				}
			}

		}*/

		return resp;
	}
	
	public static ArrayList<double[]> pointsEmptySorted(SolutionSet set2) {
		ArrayList<double[]> resp = new ArrayList<double[]>();
		HashMap<Double, double[]> sorted = new HashMap<Double, double[]>();		
		Distance distance = new Distance();
		
		Solution s1 = null, s2 = null;
		
		ArrayList<Solution> set = new ArrayList<Solution>();		
		for(int i = 0 ; i< set2.size(); i++)
		{
			set.add(set2.get(i));
		}
		
		//sort of objectives
		Collections.sort(set, new MySolutionComparator());
		
		for(int i = 0; i< set.size()-1; i++)
		{
			s1 = set.get(i);
			s2 = set.get(i+1);
			
			double d = distance.distanceBetweenObjectives(s1, s2);

			double[] r = new double[s1.getNumberOfObjectives()];
			
			for (int index = 0; index < s1.getNumberOfObjectives(); index++) {
				
				double o1 = s1.getObjective(index);
				double o2 = s2.getObjective(index);
				
				//r[index] = o1 > o2? o1:o2;
				r[index] = (o1 + o2)/2;
				
			}
			//resp.add(r);
			sorted.put(d, r);
		}
		
		Object[] keys = sorted.keySet().toArray();
		Arrays.sort(keys);
		
		for(int i = keys.length-1; i>=0 ; i--)
		{
			resp.add(sorted.get(keys[i]));
		}

		return resp;
	}
}
